﻿#region copyright
//<copyright>
// Copyright(C) 2012 TrackerRealm Corporation
// This file is part of the open source project - Jazz. http://jazz.codeplex.com
// 
// Jazz is open software: you can redistribute it and/or modify it 
// under the terms of the GNU Affero General Public License (AGPL) as published by 
// the Free Software Foundation, version 3 of the License.
// 
// Jazz is distributed in the hope that it will be useful, 
// but WITHOUT ANY WARRANTY; without even the implied warranty 
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
//  See the GNU Affero General Public License (AGPL) for more details.
// 
// You should have received a copy of the GNU General Public 
// License along with Jazz.  If not, see <http://www.gnu.org/licenses/>.
//
// REMOVAL OF THIS NOTICE IS VIOLATION OF THE COPYRIGHT. 
//</copyright>
#endregion
using System;
using System.Text;
using System.Reflection;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TrackerRealm.Jazz.Client;
using PostSharp.Extensibility;
using TrackerRealm.Jazz.Client.Custom;

namespace JazzClientTest
{
    /// <summary>
    /// A test suite that demonstrates using of the Rules within Jazz.
    /// <para>The rule feature is still under development.</para>
    /// </summary>
    [TestClass]
    public class RuleTests
    {
        #region StateExample_HappyPath_Verbose
        /// <summary>
        /// This demonstrates a correct path of execution.
        /// That is data is entered, then it is approved.
        /// See the Console output to see the details of the operations
        /// </summary>
        [TestMethod]
        public void Rule_HappyPath_Verbose()
        {
            NexusConfig config = new NexusConfig()
            {
                DataFlowEnabled = true,
                Verbose = VerboseType.All
            };
            using (ClientNexus nexus = ClientNexus.Create(config))
            {
                Basket basket = new Basket(nexus);
                Assert.IsFalse(basket.IsFull);
                Assert.AreEqual("Start", basket.CurrentState.Name);
                //
                // 
                basket.Add("Shirt");
                basket.Add("Socks");
                basket.Add("Pants");

                Assert.IsTrue(basket.IsFull);
                Assert.AreEqual("Completed", basket.CurrentState.Name);
            }
        }
        #endregion
        #region Basket Class - Used in all tests
        /// <summary>
        /// This is a small class that demonstrates the use of a "Rule" method.
        /// </summary>
        [Jazz, Observable]
        public class Basket : jObject
        {
            #region Constructor
            /// <summary>
            /// Constructor
            /// </summary>
            public Basket(ClientNexus nexus)
            :base(nexus)
            {
                this.data = new string[0];
                this.IsFull = false;
            }
            #endregion
            #region IsFull
            /// <summary>
            /// Returns true when the Request has been approved.
            /// </summary>
            [UI]
            public bool IsFull
            {
                get;
                private set;
            }
            #endregion
            #region Add
            private string[] data ;
            /// <summary>
            /// The approve method is only allowed to be executed when this instance is the 'Approval State'.
            /// </summary>
            [UI]
            public void Add(string item) 
            {
                // this is a bit messy to force the rule to fire - will be fixed.
                string[] newData = new string[data.Length + 1];
                data.CopyTo(newData, 0);
                newData[newData.Length - 1] = item;
                data = newData;
            }
            #endregion
            
            #region MyRule
            /// <summary>
            /// The approve method is only allowed to be executed when this instance is the 'Approval State'.
            /// </summary>
            [Rule]
            void MyRule()
            {
                if(data.Length >= 3)
                {
                    this.EnterState("Completed");
                }
            }
            #endregion
            #region States
            //
            // 
            //
            #region Start
            [StartState]
            void Start()
            {
                // this will be written to the console when the state is entered.
                Console.WriteLine(this.ToString() + ".StartMsg:\t\t***** Getting Started ******");
            }
            #endregion
            #region Completed
            [State]
            void Completed()
            {
                this.IsFull = true;
                // this will be written to the console when the state is entered.
                Console.WriteLine(this.ToString() + ".CompletedMsg:\t\t***** Completed ******");
            }
            #endregion
            #endregion
        }
        #endregion
    }
}
